home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 14 / CU Amiga Magazine's Super CD-ROM 14 (1997)(EMAP Images)(GB)(Track 1 of 3)[!][issue 1997-09].iso / CUCD / Programming / RKMLibsPrgs / intuition / gadgets / strhooks.c < prev    next >
C/C++ Source or Header  |  1992-09-03  |  12KB  |  349 lines

  1. ;/* strhooks.c - Execute me to compile me with SAS C 5.10
  2. LC -b1 -cfistq -v -y -j73 strhooks.c
  3. Blink FROM LIB:c.o,strhooks.o TO strhooks LIBRARY LIB:LC.lib,LIB:Amiga.lib
  4. quit
  5. */
  6.  
  7. /*
  8. Copyright (c) 1992 Commodore-Amiga, Inc.
  9.  
  10. This example is provided in electronic form by Commodore-Amiga, Inc. for
  11. use with the "Amiga ROM Kernel Reference Manual: Libraries", 3rd Edition,
  12. published by Addison-Wesley (ISBN 0-201-56774-1).
  13.  
  14. The "Amiga ROM Kernel Reference Manual: Libraries" contains additional
  15. information on the correct usage of the techniques and operating system
  16. functions presented in these examples.  The source and executable code
  17. of these examples may only be distributed in free electronic form, via
  18. bulletin board or as part of a fully non-commercial and freely
  19. redistributable diskette.  Both the source and executable code (including
  20. comments) must be included, without modification, in any copy.  This
  21. example may not be published in printed form or distributed with any
  22. commercial product.  However, the programming techniques and support
  23. routines set forth in these examples may be used in the development
  24. of original executable software products for Commodore Amiga computers.
  25.  
  26. All other rights reserved.
  27.  
  28. This example is provided "as-is" and is subject to change; no
  29. warranties are made.  All use is at your own risk. No liability or
  30. responsibility is assumed.
  31. */
  32.  
  33. /*
  34. **   strhooks.c - string gadget hooks demo
  35. **
  36. ** WARNING: This file contains "callback" functions.
  37. ** You must disable stack checking (SAS -v flag) for them to work.
  38. */
  39. #define INTUI_V36_NAMES_ONLY
  40.  
  41. #include <exec/types.h>
  42. #include <exec/memory.h>
  43. #include <utility/hooks.h>
  44. #include <devices/inputevent.h>
  45. #include <intuition/intuition.h>
  46. #include <intuition/sghooks.h>
  47. #include <graphics/displayinfo.h>
  48.  
  49. #include <clib/intuition_protos.h>
  50. #include <clib/utility_protos.h>
  51. #include <clib/exec_protos.h>
  52.  
  53. #ifdef LATTICE
  54. int CXBRK(void)    { return(0); }  /* Disable Lattice CTRL/C handling */
  55. int chkabort(void) { return(0); }  /* really */
  56. #endif
  57.  
  58. /* our function prototypes */
  59. BOOL IsHexDigit(UBYTE test_char);
  60. ULONG str_hookRoutine(struct Hook *hook, struct SGWork *sgw, ULONG *msg);
  61. void initHook(struct Hook *hook, ULONG (*ccode)());
  62. VOID handleWindow(struct Vars *vars);
  63.  
  64. struct Library    *IntuitionBase;
  65. struct Library    *UtilityBase;
  66.  
  67. #define SG_STRLEN     (44)
  68. #define MYSTRGADWIDTH (200)
  69. #define INIT_LATER      0
  70.  
  71. /* A border for the string gadget */
  72. UWORD strBorderData[] = /* init elements 5 and 7 later (height adjust) */
  73.     {
  74.     0,0,  MYSTRGADWIDTH + 3,0,  MYSTRGADWIDTH + 3,INIT_LATER,
  75.     0,INIT_LATER,   0,0,
  76.     };
  77. struct Border strBorder =
  78.     {
  79.     -2,-2, 1, 0,JAM1,5,strBorderData,NULL,
  80.     };
  81.  
  82. /* We'll dynamically allocate/clear most structures, buffers */
  83. struct Vars
  84.     {
  85.     struct Window      *sgg_Window;
  86.     struct Gadget       sgg_Gadget;
  87.     struct StringInfo   sgg_StrInfo;
  88.     struct StringExtend sgg_Extend;
  89.     struct Hook         sgg_Hook;
  90.     UBYTE               sgg_Buff[SG_STRLEN];
  91.     UBYTE               sgg_WBuff[SG_STRLEN];
  92.     UBYTE               sgg_UBuff[SG_STRLEN];
  93.     };
  94.  
  95. /*   Main entry point.
  96. **
  97. ** Open all required libraries, set-up the string gadget.
  98. ** Prepare the hook, open the sgg_Window and go...
  99. */
  100. VOID main(int argc, char **argv)
  101. {
  102. struct Vars   *vars;
  103. struct Screen   *screen;
  104. struct DrawInfo *drawinfo;
  105.  
  106. if (IntuitionBase = OpenLibrary("intuition.library", 37L))
  107.     {
  108.     if (UtilityBase = OpenLibrary("utility.library", 37L))
  109.         {
  110.         /* get the correct pens for the screen. */
  111.         if (screen = LockPubScreen(NULL))
  112.             {
  113.             if (drawinfo = GetScreenDrawInfo(screen))
  114.                 {
  115.                 vars = (struct Vars *)AllocMem(sizeof(struct Vars),MEMF_CLEAR);
  116.                 if (vars != NULL)
  117.                     {
  118.                     vars->sgg_Extend.Pens[0] = drawinfo->dri_Pens[FILLTEXTPEN];
  119.                     vars->sgg_Extend.Pens[1] = drawinfo->dri_Pens[FILLPEN];
  120.                     vars->sgg_Extend.ActivePens[0] = drawinfo->dri_Pens[FILLTEXTPEN];
  121.                     vars->sgg_Extend.ActivePens[1] = drawinfo->dri_Pens[FILLPEN];
  122.                     vars->sgg_Extend.EditHook = &(vars->sgg_Hook);
  123.                     vars->sgg_Extend.WorkBuffer = vars->sgg_WBuff;
  124.  
  125.                     vars->sgg_StrInfo.Buffer = vars->sgg_Buff;
  126.                     vars->sgg_StrInfo.UndoBuffer = vars->sgg_UBuff;
  127.                     vars->sgg_StrInfo.MaxChars = SG_STRLEN;
  128.                     vars->sgg_StrInfo.Extension = &(vars->sgg_Extend);
  129.  
  130.                     /* There should probably be a border around the string gadget.
  131.                     ** As is, it is hard to locate when disabled.
  132.                     */
  133.                     vars->sgg_Gadget.LeftEdge = 20;
  134.                     vars->sgg_Gadget.TopEdge = 30;
  135.                     vars->sgg_Gadget.Width = MYSTRGADWIDTH;
  136.                     vars->sgg_Gadget.Height = screen->RastPort.TxHeight;
  137.                     vars->sgg_Gadget.Flags = GFLG_GADGHCOMP | GFLG_STRINGEXTEND;
  138.                     vars->sgg_Gadget.Activation = GACT_RELVERIFY;
  139.                     vars->sgg_Gadget.GadgetType = GTYP_STRGADGET;
  140.                     vars->sgg_Gadget.SpecialInfo = &(vars->sgg_StrInfo);
  141.                     vars->sgg_Gadget.GadgetRender = (APTR)&strBorder;
  142.                     strBorderData[5] = strBorderData[7] =
  143.                           screen->RastPort.TxHeight + 3;
  144.  
  145.                     initHook(&(vars->sgg_Hook), str_hookRoutine);
  146.  
  147.                     if (vars->sgg_Window = OpenWindowTags(NULL,
  148.                             WA_PubScreen,       screen,
  149.                             WA_Left,      21,   WA_Top,       20,
  150.                             WA_Width,    500,   WA_Height,   150,
  151.                             WA_MinWidth,  50,   WA_MaxWidth,  ~0,
  152.                             WA_MinHeight, 30,   WA_MaxHeight, ~0,
  153.                             WA_SimpleRefresh, TRUE,
  154.                             WA_NoCareRefresh, TRUE,
  155.                             WA_RMBTrap,       TRUE,
  156.                             WA_IDCMP,         IDCMP_GADGETUP | IDCMP_CLOSEWINDOW,
  157.                             WA_Flags,         WFLG_CLOSEGADGET | WFLG_NOCAREREFRESH |
  158.                                               WFLG_DRAGBAR | WFLG_DEPTHGADGET |
  159.                                               WFLG_SIMPLE_REFRESH,
  160.                             WA_Title,         "String Hook Accepts HEX Digits Only",
  161.                             WA_Gadgets,       &(vars->sgg_Gadget),
  162.                             TAG_DONE))
  163.                         {
  164.                         handleWindow(vars);
  165.  
  166.                         CloseWindow(vars->sgg_Window);
  167.                         }
  168.                     FreeMem(vars,sizeof(struct Vars));
  169.                     }
  170.                 FreeScreenDrawInfo(screen, drawinfo);
  171.                 }
  172.             UnlockPubScreen(NULL, screen);
  173.             }
  174.         CloseLibrary(UtilityBase);
  175.         }
  176.     CloseLibrary(IntuitionBase);
  177.     }
  178. }
  179.  
  180.  
  181. /*
  182. ** This is an example string editing hook, which shows the basics of
  183. ** creating a string editing function.  This hook restricts entry to
  184. ** hexadecimal digits (0-9, A-F, a-f) and converts them to upper case.
  185. ** To demonstrate processing of mouse-clicks, this hook also detects
  186. ** clicking on a character, and converts it to a zero.
  187. **
  188. ** NOTE: String editing hooks are called on Intuition's task context,
  189. ** so the hook may not use DOS and may not cause Wait() to be called.
  190. */
  191.  
  192. ULONG str_hookRoutine(struct Hook *hook, struct SGWork *sgw, ULONG *msg)
  193. {
  194. UBYTE *work_ptr;
  195. ULONG return_code;
  196.  
  197. /* Hook must return non-zero if command is supported.
  198. ** This will be changed to zero if the command is unsupported.
  199. */
  200. return_code = ~0L;
  201.  
  202. if (*msg == SGH_KEY)
  203.     {
  204.     /* key hit -- could be any key (Shift, repeat, character, etc.) */
  205.  
  206.     /* allow only upper case characters to be entered.
  207.     ** act only on modes that add or update characters in the buffer.
  208.     */
  209.     if ((sgw->EditOp == EO_REPLACECHAR) ||
  210.         (sgw->EditOp == EO_INSERTCHAR))
  211.         {
  212.         /* Code contains the ASCII representation of the character
  213.         ** entered, if it maps to a single byte.  We could also look
  214.         ** into the work buffer to find the new character.
  215.         **
  216.         **     sgw->Code == sgw->WorkBuffer[sgw->BufferPos - 1]
  217.         **
  218.         ** If the character is not a legal hex digit, don't use
  219.         ** the work buffer and beep the screen.
  220.         */
  221.         if (!IsHexDigit(sgw->Code))
  222.             {
  223.             sgw->Actions |= SGA_BEEP;
  224.             sgw->Actions &= ~SGA_USE;
  225.             }
  226.         else
  227.             {
  228.             /* And make it upper-case, for nicety */
  229.             sgw->WorkBuffer[sgw->BufferPos - 1] = ToUpper(sgw->Code);
  230.             }
  231.         }
  232.     }
  233. else if (*msg == SGH_CLICK)
  234.     {
  235.     /* mouse click
  236.     ** zero the digit clicked on
  237.     */
  238.     if (sgw->BufferPos < sgw->NumChars)
  239.         {
  240.         work_ptr = sgw->WorkBuffer + sgw->BufferPos;
  241.         *work_ptr = '0';
  242.         }
  243.     }
  244. else
  245.     {
  246.     /* UNKNOWN COMMAND
  247.     ** hook should return zero if the command is not supported.
  248.     */
  249.     return_code = 0;
  250.     }
  251.  
  252. return(return_code);
  253. }
  254.  
  255.  
  256.  
  257. /*
  258. ** This is a function which converts register-parameter
  259. ** hook calling convention into standard C conventions.
  260. ** It only works with SAS C 5.0+
  261. **
  262. ** Without the fancy __asm stuff, you'd probably need to
  263. ** write this in assembler.
  264. **
  265. ** You could conceivably declare all your C hook functions
  266. ** this way, and eliminate the middleman (you'd initialize
  267. ** the h_Entry field to your C function's address, and not
  268. ** bother with the h_SubEntry field).
  269. **
  270. ** This is nice and easy, though, and since we're using the
  271. ** small data model, using a single interface routine like this
  272. ** (which does the necessary __saveds), it might
  273. ** actually turn out to be smaller to use a single entry point
  274. ** like this rather than declaring each of many hooks __saveds.
  275. */
  276. ULONG __saveds __asm hookEntry(register __a0 struct Hook *hookptr,
  277.     register __a2 void  *object,
  278.     register __a1 void  *message)
  279. {
  280. return((*hookptr->h_SubEntry)(hookptr, object, message));
  281. }
  282.  
  283.  
  284. /*
  285. ** Initialize the hook to use the hookEntry() routine above.
  286. */
  287. void initHook(struct Hook *hook, ULONG (*ccode)())
  288. {
  289. hook->h_Entry    = hookEntry;
  290. hook->h_SubEntry = ccode;
  291. hook->h_Data     = 0;   /* this program does not use this */
  292. }
  293.  
  294. /*
  295. ** Process messages received by the sgg_Window.  Quit when the close gadget
  296. ** is selected.
  297. */
  298. VOID handleWindow(struct Vars *vars)
  299. {
  300. struct IntuiMessage *msg;
  301. ULONG  class;
  302. USHORT code;
  303.  
  304. for (;;)
  305.     {
  306.     Wait(1L << vars->sgg_Window->UserPort->mp_SigBit);
  307.     while (msg =
  308.             (struct IntuiMessage *)GetMsg(vars->sgg_Window->UserPort))
  309.         {
  310.         /* Stash message contents and reply, important when message
  311.         ** triggers some lengthy processing
  312.         */
  313.         class = msg->Class;
  314.         code  = msg->Code;
  315.         ReplyMsg((struct Message *)msg);
  316.  
  317.         switch (class)
  318.             {
  319.             case IDCMP_GADGETUP:
  320.                 /* if a code is set in the hook after an SGH_KEY
  321.                 ** command, where SGA_END is set on return from
  322.                 ** the hook, the code will be returned in the Code
  323.                 ** field of the IDCMP_GADGETUP message.
  324.                 */
  325.                 break;
  326.             case IDCMP_CLOSEWINDOW:
  327.                 return;
  328.                 break;
  329.             }
  330.         }
  331.     }
  332. }
  333.  
  334.  
  335. /*
  336. ** IsHexDigit()
  337. **
  338. ** Return TRUE if the character is a hex digit (0-9, A-F, a-f)
  339. */
  340. BOOL IsHexDigit(UBYTE test_char)
  341. {
  342. test_char = ToUpper(test_char);
  343. if (((test_char >= '0') && (test_char <= '9')) ||
  344.     ((test_char >= 'A') && (test_char <= 'F')))
  345.     return(TRUE);
  346. else
  347.     return(FALSE);
  348. }
  349.